package app.framework.config;

import app.framework.front.interceptor.FrontInterceptor;
import app.framework.security.csrf.CsrfInterceptor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * <p>
 * SpringMVC 配置。
 * </p>
 *
 * @author mh.z
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer, ErrorPageRegistrar {
    private FrontGlobalConfig frontGlobalConfig;

    public WebMvcConfig(FrontGlobalConfig frontGlobalConfig) {
        this.frontGlobalConfig = frontGlobalConfig;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
        // 数字序列化成字符串
        builder.featuresToEnable(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);

        ObjectMapper objectMapper = builder.build();
        objectMapper.registerModule(new JavaTimeModule());
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(objectMapper);

        converters.add(1, converter);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加前端资源拦截器
        registry.addInterceptor(frontInterceptor())
                .addPathPatterns("/**");

        if (Boolean.TRUE.equals(frontGlobalConfig.getCsrfTokenEnabled())) {
            // 添加 CSRF 拦截器
            registry.addInterceptor(csrfInterceptor())
                    .addPathPatterns("/api/**");
        }
    }

    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        ErrorPage notFoundErrorPage = new ErrorPage(HttpStatus.NOT_FOUND, "/404");
        ErrorPage serverErrorPage = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500");

        // 注册错误页面
        registry.addErrorPages(notFoundErrorPage, serverErrorPage);
    }

    @Bean
    public FrontInterceptor frontInterceptor() {
        return new FrontInterceptor();
    }

    @Bean
    public CsrfInterceptor csrfInterceptor() {
        return new CsrfInterceptor();
    }

}
